﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace JSMerge {

	class Program {

		static void Main( string[] args ) {
			if ( args != null && args.Length > 0 ) {
				if ( args[0] == "/?" ) {
					WriteHelp();
					return;
				} if ( args[0].Equals( "--install", StringComparison.InvariantCultureIgnoreCase ) ) {
					InstallPath();
					return;
				} if ( args[0].Equals( "--uninstall", StringComparison.InvariantCultureIgnoreCase ) ) {
					UninstallPath();
					return;
				} else if ( args[0].EndsWith( ".jsm", StringComparison.InvariantCultureIgnoreCase ) ) {
					string projectFile = args[0];
					ProcessProject( projectFile, args );
					return;
				}
			}
			Console.WriteLine( "Invalid arguments. Use /? to get help." );
		}

		static void ProcessProject( string projectFile, string[] args ) {
			try {
				Project project = Project.FromFile( projectFile );
				Console.WriteLine( "Project loaded successfully." );
				//process additional arguments
				for ( int x = 1; x < args.Length; x++ ) {
					if ( args[x] != null && args[x].ToLower() == "-sc" && args.Length > x + 1 ) {
						if ( args[x + 1] == "0" ) {
							project.Settings.StripComments = false;
						} else if ( args[x + 1] == "1" ) {
							project.Settings.StripComments = true;
						} else {
							Console.WriteLine( "Invalid argument value for '-sc' option. Expected 0 or 1" );
							return;
						}
					} else if ( args[x] != null && args[x].ToLower() == "-sr" && args.Length > x + 1 ) {
						if ( args[x + 1] == "0" ) {
							project.Settings.StripReferences = false;
						} else if ( args[x + 1] == "1" ) {
							project.Settings.StripReferences = true;
						} else {
							Console.WriteLine( "Invalid argument value for '-sr' option. Expected 0 or 1" );
							return;
						}
					} else if ( args[x] != null && args[x].ToLower() == "-nl" && args.Length > x + 1 ) {
						if ( args[x + 1] == "0" ) {
							project.Settings.NewLine = false;
						} else if ( args[x + 1] == "1" ) {
							project.Settings.NewLine = true;
						} else {
							Console.WriteLine( "Invalid argument value for '-nl' option. Expected 0 or 1" );
							return;
						}
					} else if ( args[x] != null && args[x].ToLower() == "-o" && args.Length > x + 1 ) {
						project.OutputFile = args[x + 1];
					} else if ( args[x] != null && args[x].ToLower() == "-notags" ) {
						project.ProcessTags = false;
					}
				}
				//get the files
				Console.WriteLine( "Scanning for Javascript files..." );
				int count = project.ProcessPaths();
				Console.WriteLine( "{0} Javascript files found.", count );
				if ( count > 0 ) {
					Console.WriteLine( "Merging files..." );
					project.CombineFiles();
				} else {
					Console.WriteLine( "Merge operation stopped (no files to combine)." );
				}
			} catch ( Exception ex ) {
				Console.WriteLine( "An error occurred:" );
				Console.WriteLine( ex.ToString() );
#if DEBUG
				Console.Read();
#endif
			}
		}

		/// <summary>
		/// Installs the current directory as a global cmd path for the user.
		/// </summary>
		static void InstallPath() {
			Console.WriteLine( "Installing to User PATH:" );
			string userPath = Environment.GetEnvironmentVariable( "PATH", EnvironmentVariableTarget.User );
			string appPath = Application.StartupPath + '\\';
			if ( userPath != null && userPath.ToLower().Contains( appPath.ToLower() ) ) {
				Console.WriteLine( "Already Installed." );
				return;
			}
			Console.WriteLine( "Current PATH:" + userPath );
			if ( String.IsNullOrWhiteSpace( userPath ) ) {
				userPath = appPath;
			} else {
				userPath += ';' + appPath;
			}
			Environment.SetEnvironmentVariable( "PATH", userPath, EnvironmentVariableTarget.User );
			Console.WriteLine( "New PATH:" + userPath );
			Console.WriteLine();
			Console.WriteLine( "Install Complete." );
		}

		/// <summary>
		/// Removes the current directory as a cmd path for the user.
		/// </summary>
		static void UninstallPath() {
			string userPath = Environment.GetEnvironmentVariable( "PATH", EnvironmentVariableTarget.User );
			string appPath = Application.StartupPath + '\\';
			int index = ( userPath ?? "" ).ToLower().IndexOf( appPath, 0, StringComparison.InvariantCultureIgnoreCase );
			if ( index > -1 ) {
				int len = appPath.Length;
				if ( index > 0 && userPath[index - 1] == ';' ) {
					//remove prefixed ';'
					index--;
					len++;
				} else if ( index + 1 + len < userPath.Length - 1 && userPath[index + 1 + len] == ';' ) {
					//remove postfixed ';'
					len++;
				}
				userPath = userPath.Remove( index, len );
				userPath = userPath.Trim( new char[] { ';' } );
				Environment.SetEnvironmentVariable( "PATH", userPath, EnvironmentVariableTarget.User );
				Console.WriteLine( "Uninstall Complete." );
			} else {
				Console.WriteLine( "Directory '" + appPath + "' not found in PATH variable. No need to uninstall." );
			}
		}

		static void WriteHelp() {
			WriteHeader();
			Console.WriteLine( "Usage:" );
			Console.WriteLine( "jsmerge {special} {project} {options}" );
			Console.WriteLine();
			Console.WriteLine( "{project}".PadRight( 30 ) + "The JSMerge project file name to utilize." );
			Console.WriteLine();
			Console.WriteLine( "{special}" );
			Console.WriteLine( "/?".PadRight( 30 ) + "Show this help information." );
			Console.WriteLine( "--install".PadRight( 30 ) + "Installs JSMerge to the global path." );
			Console.WriteLine( "--uninstall".PadRight( 30 ) + "Uninstalls JSMerge from the global path.." );
			Console.WriteLine();
			Console.WriteLine( "{options}" );
			Console.WriteLine( "-o {output}".PadRight( 30 ) + "Override the project file output file name." );
			Console.WriteLine( "-notags".PadRight( 30 ) + "Merges the files without processing JSMerge tags." );
			Console.WriteLine( "-sc {0/1}".PadRight( 30 ) + "Override the project's setting to strip comments with the given value." );
			Console.WriteLine( "-sr {0/1}".PadRight( 30 ) + "Override the project's setting to strip VS2012 reference tags with the given value." );
			Console.WriteLine( "-nl {0/1}".PadRight( 30 ) + "Override the project setting to add a New Line after every file." );
			Console.WriteLine();
			Console.WriteLine( "Where indicated, 0= False and 1= True" );
		}

		static void WriteHeader() {
			Console.WriteLine( Application.ProductName );
			Console.WriteLine( Application.ProductVersion );
			Console.WriteLine();
		}

	}
}

